/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package edu.ncsu.external_sensors;

import com.sun.spot.core.resources.transducers.ISwitch;
import com.sun.spot.core.resources.transducers.ISwitchListener;
import com.sun.spot.edemo.EDemoBoard;

/**
 * A utility for working with the EDemoBoard's switches.  Note that if the user presses both switches, one
 * switch will register its event before the other one.  Its immediatePress method will be called, but if the other is pressed
 * before the immediatePress method finishes, the first's event will die and the second's will register as a doublePress.  If the second switch is
 * pressed after the immediatePress method finishes, the first switch's deliberatePress method will also be called before the doublePress event
 * is detected.
 * 
 * Remember to register instances of your subclass of EDemoSwitchClickListener to both sw2 and sw1
 * @author Douglas McClusky
 */
public abstract class EDemoSwitchClickListener implements ISwitchListener {
    private boolean doublePress = false;
    private boolean hold1, hold2, doubleHold = false;
    /**
     * The EDemoBoard's switches
     */
    protected static ISwitch[] sw = EDemoBoard.getInstance().getSwitches();
    
    public void switchPressed(ISwitch arg0) {
        boolean press1 = sw[0].isClosed();
        boolean press2 = sw[1].isClosed();
        doublePress = (press1 && press2);
        synchronized (sw) {
            if (doublePress) {
                doubleHold = false;
                immediateDoublePress();
                if (sw[0].isClosed() && sw[1].isClosed()) {
                    doubleHold = true;
                    deliberateDoublePress();
                }
                return;
            }
            if (press1) {
                hold1 = false;
                immediatePress1();
                if (doublePress) {
                    return;
                }
                if (sw[0].isClosed()) {
                    hold1 = true;
                    deliberatePress1();
                }
                return;
            }
            if (press2) {
                hold2 = false;
                immediatePress2();
                if (doublePress) {
                    return;
                }
                if (sw[1].isClosed()) {
                    hold2 = true;
                    deliberatePress2();
                }
                return;
            }
        }
    }
    
    /**
     * This method is called when sw2 is pressed
     */
    protected abstract void immediatePress1();
    /**
     * This method is called when sw1 is pressed
     */
    protected abstract void immediatePress2();
    /**
     * This method is called when both sw2 and sw1 are pressed together
     */
    protected abstract void immediateDoublePress();
    
    /**
     * This method is called when sw1 only is held until the immediatePress method finishes.
     * For instance, if the immediatePress method displays something on the LEDs and sleeps for a second, 
     * the user would have to hold down sw1 for a second.
     */
    protected abstract void deliberatePress1();
    
    /**
     * This method is called when sw2 only is held until the immediatePress method finishes.
     * For instance, if the immediatePress method displays something on the LEDs and sleeps for a second, 
     * the user would have to hold down sw2 for a second.
     */
    protected abstract void deliberatePress2();
    
    /**
     * This method is called when both sw2 and sw1 are held together until the immediatePress method finishes.
     * For instance, if the immediatePress method displays something on the LEDs and sleeps for a second, 
     * the user would have to hold down both switches for a second.
     */
    protected abstract void deliberateDoublePress();
    
    public void switchReleased(ISwitch arg0) {
        if (doublePress) {
            if (sw[0].isOpen() && sw[1].isOpen()) {
                if (!doubleHold) {
                    doubleClick();
                }
            }
        } else {
            if (sw[0].equals(arg0) && !hold1) {
                click1();
            }
            if (sw[1].equals(arg0) && !hold2) {
                click2();
            }
        }
    }
    
    /**
     * This method is called if sw2 is pressed and released before the immediatePress method finishes
     */
    protected abstract void click1();
    /**
     * This method is called if sw1 is pressed and released before the immediatePress method finishes
     */
    protected abstract void click2();
    /**
     * This method is called if both sw2 and sw1 are pressed together and released before the immediatePress method finishes
     */
    protected abstract void doubleClick();
}
